﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.Notifications;
using Common.DataAccess;
using CBE.Model;

namespace CBE.DataAccess
{
    public class AdministrarPromocionesDataAccess : GenericEntityManagerDataAccess<Promociones, AdministrarPromocionesCriteria, AdministrarPromocionesView, CBEEntities>
    {

        protected override Promociones ReadEntity(Guid id)
        {
            return ObjectContext.Promociones.
                   Include("Clientes").
                   Include("Dias").
                   Include("Servicios").
                   Where(promocion => promocion.ID_Promocion == id).
                   FirstOrDefault();
        }

        public override List<AdministrarPromocionesView> Read(AdministrarPromocionesCriteria criteria)
        {
            return ObjectContext.Promociones.
                Where(promocion => (String.IsNullOrEmpty(criteria.Codigo) || promocion.Codigo.Contains(criteria.Codigo)) &&
                                   (String.IsNullOrEmpty(criteria.Descripcion) || promocion.Descripcion.Contains(criteria.Descripcion)) &&
                                   (criteria.IDServicio == Guid.Empty || promocion.Servicios.Any(s => s.ID_Servicio == criteria.IDServicio)) &&
                                   (
                                        (!criteria.FechaInicioDesde.HasValue || criteria.FechaInicioDesde.Value <= promocion.FechaInicio.Value) &&
                                        (!criteria.FechaInicioHasta.HasValue || criteria.FechaInicioHasta.Value >= promocion.FechaInicio.Value)
                                   ) &&
                                   (
                                        (!criteria.FechaFinDesde.HasValue || criteria.FechaFinDesde.Value <= promocion.FechaFin.Value) &&
                                        (!criteria.FechaFinHasta.HasValue || criteria.FechaFinHasta.Value >= promocion.FechaFin.Value)
                                   )
                                   ).
                Select(promocion => new AdministrarPromocionesView
                {
                    ID = promocion.ID_Promocion,
                    Codigo = promocion.Codigo,
                    Descripcion = promocion.Descripcion,
                    Descuento = promocion.Bonificacion,
                    FechaInicio = promocion.FechaInicio.Value,
                    FechaFin = promocion.FechaFin.Value,
                    Servicios = promocion.Servicios.Select(ser => ser.Descripcion)
                }).OrderBy(prom => prom.Codigo).ToList();
        }

        public override List<Promociones> ReadEntities()
        {
            var hoy = DateTime.Now.Date;

            return ObjectContext.Promociones.
                   Include("Clientes").
                   Include("Servicios").
                   Where(promo => promo.FechaInicio.Value <= hoy && promo.FechaFin.Value >= hoy).
                   ToList();
        }

        protected override void AfterSave(Promociones entity)
        {
            if (entity.EsPromocionPublica.HasValue &&
                !entity.EsPromocionPublica.Value)
            {
                this.NotificaPromocion(entity);
            }
        }

        private void NotificaPromocion(Promociones entity)
        {
            //en promociones. enviar mail o sms a:
            //OPC 1: los clientes elegidos
            //OPC 2: los TOP X clientes
            var clientes = new List<Clientes>();
            foreach (var item in entity.Clientes)
            {
                clientes.Add(item);
            }

            if (entity.TopNumeroClientes.HasValue && entity.TopNumeroClientes.Value != 0)
            {
                foreach (var item in this.ObtenerClientesTOPX(entity.TopNumeroClientes.Value))
                {
                    clientes.Add(item);
                }
            }

            if (entity.NotificaPorMail.HasValue && entity.NotificaPorMail.Value)
            {
                //notifica por mail
                this.EnvioPorMail(entity, clientes);
            }
        }

        private List<Clientes> ObtenerClientesTOPX(int top)
        {
            AdministrarClientesDataAccess daClientes = new AdministrarClientesDataAccess();
            var list = daClientes.ReadTOPXClientesPorImporteVenta(top);

            if (list == null)
            {
                return new List<Clientes>();
            }
            return list;
        }

        private void EnvioPorMail(Promociones entity, List<Clientes> clientes)
        {
            var textoMail = entity.GetTextoMail();
            Notification.SendEmail(clientes.Where(c => !String.IsNullOrEmpty(c.Mail)).Select(c => c.Mail).ToList(),
                String.Format("{0} - nueva promoción!", Empresa.Nombre),
                textoMail);

        }

        public override void Save(Promociones entity)
        {
            this.ValidateNumeroPromocion(entity);
            base.Save(entity);
        }

        private void ValidateNumeroPromocion(Promociones entity)
        {
            if (ObjectContext.Promociones.Any(pr => pr.Codigo.ToUpper() == entity.Codigo.ToUpper() && pr.ID_Promocion != entity.ID_Promocion))
            {
                throw new Exception("Ya existe una promoción con el código ingresado.");
            }
        }
    }
}
